package com.lmmob.autotest.uitest.controls;

import com.lmmob.autotest.uitest.formmodel.FormElement;

import org.apache.commons.lang.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

import javax.annotation.Nullable;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.matchers.JUnitMatchers.containsString;

public class TextBox extends Control implements ValueSettable {
    private String name;

    public TextBox(String name, WebDriver webDriver) {
        super(webDriver);
        this.name = name;
    }

    private boolean isError() {
        try {
            WebDriverWait wait = new WebDriverWait(webDriver, 8);
            return wait.until(new ExpectedCondition<Boolean>() {
                public Boolean apply(@Nullable WebDriver webDriver) {
                    return Boolean.valueOf(getInputElement().getAttribute("aria-invalid"));
                }
            });
        } catch (TimeoutException e) {
            fail(String.format("TextBox[name='%s'] thrown timeout exception", this.name));
            return false;
        }
    }

    public boolean isReadOnly() {
        return true;
    }

    public void verifyError(FormElement formElement) {
        if (formElement == null || StringUtils.isBlank(formElement.getErrorMessage())) return;
        assertThat(String.format("TextBox[name='%s']应该提示错误信息", this.name), isError(), is(true));
        assertThat(String.format("TextBox[name='%s']提示的错误信息有误", this.name), errorMessage(), containsString(formElement.getErrorMessage()));
    }

    private String errorMessage() {
        String errorMessageId = (String) runScript(String.format("return %s.query(\"[id='%s']\")[0].errorEl.id", this.getParent().getQuery(), this.getId()));
        return findElement(By.id(errorMessageId)).getText();
    }

    public void verifyValue(String expected) {
        assertThat(String.format("TextBox[name='%s']", this.name), getValue(), containsString(expected));
    }

    @Override
    protected String getName() {
        return this.name;
    }

    @Override
    protected String getSelfQuery() {
        return String.format(".query(\"textfield[name='%s']\")[0]", this.name);
    }

    public void setValue(String value) {
        WebElement inputElement = getInputElement();
        inputElement.clear();
        inputElement.sendKeys(value);
    }

    public String getValue() {
        return getInputElement().getAttribute("value");
    }

    private WebElement getInputElement() {
        return findElement(By.id(getId())).findElement(By.tagName("input"));
    }


}
